require('./global.js');
var mysql = require('mysql');
var mongodb = require('mongodb');

function GameServerDesc(id) {
    this.id = id;
    this.time = 0;
    this.stamp = 0;
    this.host = '';
    this.version = '';
    this.merged = 0;
    this.leagueWarTime = 0;
    this.dbHostId = '';
    this.dbName = '';
    /*
    hostId = '';
    hostIP = '';
    gatewayPort = 0,
    payPort = 0,
    */

    this.isValid = function() {
        if (this.merged != 0 && this.merged != this.id) {
            return false;
        }

        if (this.stamp >= Date.getStamp()) {
            return false;
        }

        return true;
    }

    this.getRealId = function() {
        return this.merged || this.id;
    }
}

function DBServerDesc(id) {
    this.id = id;
    this.ip = '';
    this.port = 0;
    this.client = null;
}


function ServerManager() {
    this.gameServers = {}; 
    this.dbServers = {};
    this.error = null;

    /*
    desc    :加载游戏服务器列表
    param   :callback,回调接口,参数
                :error,错误信息
    */
    this.loadGame = function(callback) {
        this.error = null;

        var options = {
            host : config.mysql.ip,
            port : config.mysql.port,
            user : config.mysql.user,
            password : config.mysql.password,
            database : 'login',
            insecureAuth: true,
        };
        
        var connection = mysql.createConnection(options);
        var gameServers = {};

        async.series([
            function(cb) {
                connection.connect(function(err) {
                    cb(err);
                });
            },

            function(cb) {
                var sql = 'SELECT id,time,UNIX_TIMESTAMP(time) as stamp,host,version,merged,league_war_time FROM server';
                connection.query(sql, function(err, res, fields) {
                    if (err) {
                        cb(err);
                        return;
                    }

                    for (var i = 0; i < res.length; ++i) {
                        var item = res[i];
                        var id = +item.id;

                        var server = new GameServerDesc(id);
                        server.id = id;
                        server.time = item.time;
                        server.stamp = +item.stamp;
                        server.host = item.host;
                        server.version = +item.version;
                        server.merged = +item.merged;
                        server.leagueWarTime = +item.league_war_time;
                        server.dbHostId = config.game.db_host_id(server.id);
                        server.dbName = config.game.db_name(server.id, server.merged);
                        gameServers[id] = server;
                    }

                    cb();
                });
            },

            function(cb) {
                var sql = 'SELECT * FROM server_d';
                connection.query(sql, function(err, res, fields) {
                    if (err) {
                        cb(err);
                        return;
                    }

                    for (var i = 0; i < res.length; ++i) {
                        var item = res[i];
                        var id = +item.id;

                        var server = gameServers[id];
                        if (!server) {
                            continue;
                        }

                        server.hostId = item.host_id;
                        server.hostIP = item.host_ip;
                        server.gatewayPort = item.gateway_port;
                        server.payPort = item.pay_port;
                    }

                    cb();
                });
            },

            function(cb) {
                connection.end();
                cb();
            },
        ], function(err, results) {
            if (err) {
                this.error = error;
                callback && callback(err);
                return;
            }
            for (var id in gameServers) {
                var server = gameServers[id];
                if (!server.hostId) {
                    delete gameServers[id];
                }
            }

            this.gameServers = gameServers;
            callback && callback();
        }.bind(this));
    };

    /*
    desc    :加载数据库服务器列表
    param   :option,选项参数
                :native,是否启用native_parser,默认为true;
                :slave, 是否连接备份数据库,默认为true;
    param   :callback,回调接口,参数
                :error,错误信息
    */
    this.loadDB = function(option, callback) {
        this.error = null;

        var hosts = [];
        var hostConfigs = config.server.host;
        for (var id in hostConfigs) {
            var hostConfig = hostConfigs[id];
            if (hostConfig.mongo && hostConfig.mongo.slave) {
                if (getValueWithDefault(option.slave, true)) {
                    hostConfig = hostConfigs[hostConfig.mongo.slave];
                }
                hosts.push({
                    id: id, 
                    ip: hostConfig.ip,
                    port: +hostConfig.mongo.port,
                });
            }
        }
        
        var dbServers = {};
        async.each(hosts, function(host, cb) {
            var mongoServer = new mongodb.Server(host.ip, host.port, {native_parser: getValueWithDefault(option.native, true)});
            var mongoClient = new mongodb.MongoClient(mongoServer);
            mongoClient.open(function(err, mc) {
                if (!err) {
                    var server = new DBServerDesc(host.id);
                    server.ip = host.ip;
                    server.port = host.port;
                    server.client = mongoClient;
                    dbServers[server.id] = server;
                }
                cb(err);
            });
        },
        function(err) {
            if (err) {
                this.error = err;
                callback && callback(err);
                return;
            }

            this.dbServers = dbServers;
            callback && callback();
        }.bind(this));
    }

    this.load = function(option, callback) {
        this.loadGame(function(err) {
            if (err) {
                callback && callback(err);
                return;
            }

            this.loadDB(option, callback);
        }.bind(this));
    }

    this.getGameServerDB = function(gameServer) {
        var dbServer = this.dbServers[gameServer.dbHostId];
        return dbServer && dbServer.client && dbServer.client.db(gameServer.dbName);
    }

    this.getGameDB = function(sid) {
        var server = this.gameServers[sid];
        return server && server.isValid() && this.getGameServerDB(server);
    }

    this.getSids = function(minSid, maxSid) {
        minSid = minSid || 0;
        maxSid = maxSid || UINT16_MAX;
        var sids = []; 

        for (id in this.gameServers) {
            if (id >= minSid && id <= maxSid && this.gameServers[id].isValid()) {
                sids.push(id);
            }
        }

        return sids;
    }

    this.getDescSids = function(desc) {
        var sids = [];
        if ('all' == desc) {
            sids = this.getSids();
        } else {
            var descArr = desc.split('-');
            if (descArr.length >= 2) {
                var minSid = descArr[0];
                var maxSid = descArr[1];
                if (!isNaN(minSid) && !isNaN(maxSid)) {
                    sids = this.getSids(+minSid, +maxSid);
                }
            } else {
                if (!isNaN(desc)) {
                    var sid = +desc;
                    var server = this.gameServers[sid];
                    if (server && server.isValid()) {
                        sids.push(sid);
                    }
                }
            }
        }
        return sids;
    }
}

exports.ServerManager = ServerManager;
